<template>
    <div class="chat-col chat-col-3">
        <div class="chatBox" ref="chatBox">
            <div class="chat-content" v-for="item, index in messages">
                <div class="role" v-if="item.role == 'user'">
                    <img src="@/assets/role/user.svg" alt="">
                </div>
                <div class="role" v-else>
                    <img src="@/assets/role/assistant.svg" alt="">
                </div>
                <div :class="item.role" v-html="item.content"></div>
                <!-- <tiptapComponent :content="item.content" /> -->
            </div>
        </div>
        <div class="inputBox">
            <div class="inputBox-container">
                <input class="inputMessage" type="text" v-model="prompt" @keyup.enter="sendMessage">
                <button class="send" @click="sendMessage"><img src="../assets/svg/send.svg" alt=""></button>
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { ref, onUnmounted, onUpdated } from 'vue';
import type { Message } from "@/type/index";
import { fetchEventSource } from "@microsoft/fetch-event-source";
import MarkdownIt from 'markdown-it';
const markdownIt = new MarkdownIt()

const prompt = ref<string>('');
const messages = ref<Message[]>([]);
const chatBox = ref<HTMLDivElement | null>(null);

// const that = this;

const chatUrl = 'http://localhost:3000/chat';
let eventSource: EventSource | null = null;

const sendMessage = async () => {
    if (prompt.value.trim() !== '') {
        messages.value.push({ role: 'user', content: prompt.value });
        const latestEntries = messages.value.slice(-5);
        listenToMessages(latestEntries);
        prompt.value = ''; // 重置输入框
    }
};

class RetriableError extends Error { }
class FatalError extends Error { }

/**
 * 
 * @description 向后端发送消息并监听SSE响应
 */
const listenToMessages = (messages: Message[]) => {
    // 关闭旧的连接
    if (eventSource) {
        console.log('duankai');
        
        eventSource.close();
    }

    const ctrl = new AbortController();
    fetchEventSource(chatUrl, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({ messages: messages }),
        signal: ctrl.signal,
        // async onopen(response: Response) {
        //     if (response.ok && response.headers.get('content-type') === EventStreamContentType) {
        //         return; // everything's good
        //     } else if (response.status >= 400 && response.status < 500 && response.status !== 429) {
        //         // client-side errors are usually non-retriable:
        //         throw new FatalError();
        //     } else {
        //         throw new RetriableError();
        //     }
        // },
        onmessage(event: any) {
            console.log(event);
            handleSSEData(event.id, event.data);
        },
        onerror(error: any) {
            console.error('EventSource failed with error:', error);
            eventSource?.close();
        },
        // onclose() {
        //     // if the server closes the connection unexpectedly, retry:
        //     throw new RetriableError();
        // },
    })
};

/**
 * 
 * @description 处理SSE流数据
 */
const handleSSEData = (id: string, data: any) => {
    const eventData = JSON.parse(data);
    console.log(id, eventData);

    const { output, usage, request_id } = eventData;
    const { text, finish_reason } = output;

    if (id === '1') {
        messages.value.push({ role: 'assistant', content: markdownIt.render(text) });
    } else {
        messages.value[messages.value.length - 1] = { role: 'assistant', content: markdownIt.render(text) };

    }

};

onUnmounted(() => {
    if (eventSource) {
        eventSource.close();
    }
});

const scrollToBottom = () => {
    chatBox.value?.scrollTo({ top: chatBox.value.scrollHeight, behavior: 'smooth' });
};

onUpdated(scrollToBottom);

</script>


<style lang="scss">
.chat-col-3 {
    flex: 0 0 83.33333333%;
    position: relative;
    width: calc(100% - 312px);
    min-width: calc(100% - 312px);
    max-width: calc(100% - 312px);
    height: 100%;
    display: flex;
    flex-direction: column;

    .chatBox {
        width: 100%;
        display: flex;
        flex-direction: column;
        height: calc(100% - 90px);
        overflow-y: scroll;
        box-sizing: border-box;

        .chat-content {
            display: flex;
            padding: 40px 16px;

            .user {
                margin-left: 30px;
            }

            .assistant {
                margin-left: 30px;

                code {
                    background-color: rgba(#616161, 0.1);
                    color: #616161;
                }

                pre {
                    background: #282c34;
                    color: #FFF;
                    font-family: 'JetBrainsMono', monospace;
                    padding: 0.75rem 1rem;
                    border-radius: 0.5rem;

                    code {
                        color: #7fb421;
                        padding: 0;
                        background: none;
                        font-size: 0.8rem;
                    }
                }

            }
        }

        .chat-content:nth-child(even) {
            background-color: #eee;
        }
    }


    .inputBox {
        width: 90%;
        height: 90px;
        max-height: 90px;
        padding: 0 5% 10px;

        .inputBox-container {
            width: 100%;
            height: auto;
            box-shadow: 0 0 3px #2b2d31;
            justify-items: center;
            border-radius: 4px;
            display: flex;
            align-items: center;
            margin-top: 25px;

            .inputMessage {
                width: calc(100% - 18px - 32px);
                padding: 6px 6px 6px 10px;
                height: 100%;
                border: none;
            }

            .inputMessage:focus {
                border-color: transparent !important;
                outline: none;
            }
        }

        .send {
            padding: 2px;
            border: none;
            background: none !important;
        }

    }








}









/* code {
    display: block;
    padding: 10px; 
    background-color: #861313 !important; 
    border-radius: 5px;
    font-family: monospace; 
    font-size: 14px;
    line-height: 1.5; 
    overflow-x: auto; 
}

code::before {
    content: attr(data-line-number); 
    display: inline-block; 
    margin-right: 10px; 
    color: #999; 
} */
</style>